package vn.ikame.android.boojtran.truyenbua.object;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import vn.ikame.android.boojtran.truyenbua.download.DownloadPic;
import vn.ikame.android.boojtran.truyenbua.download.IDownloadPicHandler;
import vn.ikame.android.boojtran.truyenbua.utility.StorageUtils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.Display;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

public class PicView extends View implements IDownloadPicHandler {
	// We can be in one of these 3 states
	static final int NONE = 0;
	static final int DRAG = 1;
	static final int ZOOM = 2;
	int mode = NONE;

	public float pPressDim = 200;
	public float Xpress;
	public float Ypress;
	public boolean touchMoved;
	private Bitmap image;
	private boolean showImage;
	private Paint imagePaint;
	private Paint paintFullColor;
	private Paint textPaint;
	private RectF imageDispRect = new RectF();
	private RectF imagePressRect = new RectF();
	private Rect imageRect = new Rect();
	private RectF imageMiniRect = new RectF();
	private boolean isMiniShow;
	private String photoUrl;
	private String mess = "Đang tải...";
	private String message;
	private boolean downloading = false;

	private GestureDetector gestureDetector;
	Context context;

	public PicView(Context context) {
		super(context);
		init(context);
		this.context = context;
	}

	public PicView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
		this.context = context;
	}

	public PicView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
		this.context = context;
	}

	public void init(Context context) {
		this.context = context;
		showImage = false;
		isMiniShow = false;
		paintFullColor = new Paint();
		paintFullColor.setStyle(Style.FILL);
		paintFullColor.setColor(Color.WHITE);
		paintFullColor.setAntiAlias(true);

		textPaint = new Paint();
		textPaint.setTextAlign(Align.CENTER);
		textPaint.setColor(Color.WHITE);
		textPaint.setTextSize(100 * (getRight() - getLeft()) / 400);
		textPaint.setAntiAlias(true);

		imagePaint = new Paint();
		imagePaint.setAntiAlias(true);
		postInvalidate();
		gestureDetector = new GestureDetector(context, new GestureListener());
		message = mess;
		downloading = false;
		// start();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		canvas.drawColor(Color.BLACK);
		if (showImage) {
			if (image != null)
				canvas.drawBitmap(image, imageRect, imageDispRect, null);
		} else
			canvas.drawText(message, (getRight() - getLeft()) / 2,
					(getBottom() + getTop()) / 2, textPaint);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		textPaint.setTextSize(30 * (getRight() - getLeft()) / 400);
		if (image != null)
			showMinSize();
		postInvalidate();
	}

	public void showImage(String imagePath) {
		if (image != null) {
			image.recycle();
			image = null;
		}
		try {
			System.gc();
			image = decodeFile(imagePath);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (image == null) {
			showImage = false;
		} else {
			showImage = true;
			imageRect.set(0, 0, image.getWidth(), image.getHeight());
			showMinSize();
		}
		postInvalidate();
		System.gc();
	}

	// decodes image and scales it to reduce memory consumption
	private Bitmap decodeFile(String filePath) {
		try {
			// Decode image size
			BitmapFactory.Options o = new BitmapFactory.Options();
			o.inJustDecodeBounds = true;
			BitmapFactory.decodeStream(new FileInputStream(filePath), null, o);

			// The new size we want to scale to
			WindowManager wm = (WindowManager) context
					.getSystemService(Context.WINDOW_SERVICE);
			Display display = wm.getDefaultDisplay();
			final int REQUIRED_SIZE = display.getWidth();

			// Find the correct scale value. It should be the power of 2.
			int scale = 1;
			while (o.outWidth / scale / 2 >= REQUIRED_SIZE
					&& o.outHeight / scale / 2 >= REQUIRED_SIZE)
				scale *= 2;

			// Decode with inSampleSize
			BitmapFactory.Options o2 = new BitmapFactory.Options();
			o2.inSampleSize = scale;
			return BitmapFactory.decodeStream(new FileInputStream(filePath),
					null, o2);
		} catch (FileNotFoundException e) {
		} catch (OutOfMemoryError e) {
			e.printStackTrace();
			System.gc();
			try {
				return BitmapFactory.decodeFile(filePath);
			} catch (OutOfMemoryError e2) {
				e2.printStackTrace();
			}
		}
		return null;
	}

	public void setImageUrl(String url) {
		// hideImage();
		this.photoUrl = url;
		loadImage();
	}

	@Override
	public void onDownloadFinish(int index) {
		downloading = false;
		System.out.println("VKL: download succes=" + photoUrl);
		loadImage();
	}

	@Override
	public void onDownloadError(int index) {
		downloading = false;
		System.out.println("VKL: download fail=" + photoUrl);
		loadImage();
	}

	@Override
	public void downloadProgress(int progress) {
		// System.out.println("VKL: download progress=" + progress);
		message = mess + progress + "%";
		postInvalidate();
	}

	public void loadImage() {
		if (!downloading) {
			String imagePath;
			if (photoUrl == null)
				return;
			imagePath = StorageUtils.getPathFileSaveFromUrl(
					context.getApplicationContext(), photoUrl);
			// ton tai file thi load len webview
			if (new File(imagePath).exists()) {
				System.out.println("VKL: view= " + imagePath);
				showImage(imagePath);
				System.gc();
				return;
			}
			hideImage();
			// khong ton tai thi download
			downloading = true;
			DownloadPic downloadPic = new DownloadPic(this);
			downloadPic.download(photoUrl);
		}
	}

	// hien anh voi kich co chuan, lon hon thi thu nho lai
	private void showMinSize() {
		// float scale = (float) imageRect.width() / getWidth() > (float)
		// imageRect
		// .height() / getHeight() ? (float) imageRect.width()
		// / getWidth() : (float) imageRect.height() / getHeight();
		WindowManager wm = (WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE);
		Display display = wm.getDefaultDisplay();
		float scale = (float) imageRect.width() / display.getWidth();
		if (scale <= 1) {
			scale = 1;
		}
		float w = imageRect.width() / scale;
		float h = imageRect.height() / scale;
		float xc = getLeft() + getRight() / 2;
		float yc = getTop();
		imageMiniRect.set(xc - w / 2, yc, xc + w / 2, yc + h);
		imageDispRect.set(xc - w / 2, yc, xc + w / 2, yc + h);
		isMiniShow = true;
	}

	public void hideImage() {
		showImage = false;
		postInvalidate();
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// gestureDetector.onTouchEvent(event);
		int pointerCount = event.getPointerCount();
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Xpress = event.getX();
			Ypress = event.getY();
			touchMoved = false;
			imagePressRect.set(imageDispRect);
			mode = DRAG;
			if (pointerCount == 2) {
				XuLyThaoTac(event);
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if (pointerCount == 2) {
				XuLyThaoTac(event);
			}
			if (pointerCount == 1 && mode == DRAG) {
				MovePic(event.getX() - Xpress, event.getY() - Ypress);
				Xpress = event.getX();
				Ypress = event.getY();
			}
			touchMoved = true;
			break;
		case MotionEvent.ACTION_UP:
			touchMoved = false;
			break;
		}
		postInvalidate();
		return true;
	}

	public void actionDown(MotionEvent event) {
		int pointerCount = event.getPointerCount();
		Xpress = event.getX();
		Ypress = event.getY();
		touchMoved = false;
		imagePressRect.set(imageDispRect);
		mode = DRAG;
		if (pointerCount == 2) {
			XuLyThaoTac(event);
		}
	}

	public void actionMove(MotionEvent event) {
		int pointerCount = event.getPointerCount();
		if (pointerCount == 2) {
			XuLyThaoTac(event);
		}
		if (pointerCount == 1 && mode == DRAG) {
			MovePic(event.getX() - Xpress, event.getY() - Ypress);
			Xpress = event.getX();
			Ypress = event.getY();
		}
		touchMoved = true;
	}

	public void actionUp(MotionEvent event) {
		// gestureDetector.onTouchEvent(event);
		touchMoved = false;
	}

	public GestureDetector getGestureDetector() {
		return this.gestureDetector;
	}

	public void actionFinish() {
		postInvalidate();
	}

	private void XuLyThaoTac(MotionEvent e) {
		int firstIndex = e.getX(0) < e.getX(1) ? 0 : 1;
		int secondIndex = e.getX(0) < e.getX(1) ? 1 : 0;
		float dX = e.getX(secondIndex) - e.getX(firstIndex);
		float dY = e.getY(secondIndex) - e.getY(firstIndex);
		float tyLe = (float) Math.sqrt(dX * dX + dY * dY) / pPressDim;
		if (mode == ZOOM)
			ZoomPic((e.getX(0) + e.getX(1)) / 2, (e.getX(0) + e.getX(1)) / 2,
					tyLe);
		else {
			pPressDim = (float) Math.sqrt(dX * dX + dY * dY);
			mode = ZOOM;
		}
	}

	private void ZoomPic(float x0, float y0, float tyLe) {
		System.out.println("ZoomPic: " + tyLe);
		System.out.println("imageDispRect: " + imageDispRect.width() + ","
				+ imageDispRect.height());
		isMiniShow = false;
		if (image == null)
			return;
		float pLeft, pTop, pWidth, pHeight;
		pWidth = imagePressRect.width() * tyLe;
		pHeight = imagePressRect.height() * tyLe;
		System.out.println("pWidth: " + pWidth);
		if (tyLe > 1 && pWidth > image.getWidth() * 3)
			return;
		if (pWidth > getWidth() && pHeight > getHeight()) {
			pLeft = (imagePressRect.left - x0) * tyLe + x0;
			pTop = (imagePressRect.top - y0) * tyLe + y0;
			if (pLeft < getWidth() - pWidth)
				pLeft = getWidth() - pWidth;
			if (pLeft > 0)
				pLeft = 0;
			if (pTop < getHeight() - pHeight)
				pTop = getHeight() - pHeight;
			if (pTop > 0)
				pTop = 0;
			imageDispRect.set(pLeft, pTop, pLeft + pWidth, pTop + pHeight);
		}
		if (pWidth > getWidth() && pHeight <= getHeight()) {
			pLeft = (imagePressRect.left - x0) * tyLe + x0;
			if (pLeft < getWidth() - pWidth)
				pLeft = getHeight() - pWidth;
			if (pLeft > 0)
				pLeft = 0;
			pTop = (getHeight() - pHeight) / 2;
			imageDispRect.set(pLeft, pTop, pLeft + pWidth, pTop + pHeight);
		}
		if (pWidth <= getWidth() && pHeight > getHeight()) {
			pTop = (imagePressRect.top - y0) * tyLe + y0;
			if (pTop < getHeight() - pWidth)
				pTop = getHeight() - pWidth;
			if (pTop > 0)
				pTop = 0;
			pLeft = (getWidth() - pWidth) / 2;
			imageDispRect.set(pLeft, pTop, pLeft + pWidth, pTop + pHeight);
		}
		System.out.println("imageDispRect 1: " + imageDispRect.width() + ","
				+ imageDispRect.height());
		if (tyLe < 1 && pWidth < imageMiniRect.width()
				&& pHeight < imageMiniRect.height()) {
			showMinSize();
		}

	}

	public void MovePic(float dx, float dy) {
		if (image == null)
			return;
		float pLeft, pTop, pWidth, pHeight;
		pWidth = imageDispRect.width();
		pHeight = imageDispRect.height();
		if (pWidth > getWidth() && pHeight > getHeight()) {
			pLeft = imageDispRect.left + dx;
			pTop = imageDispRect.top + dy;
			if (pLeft < getWidth() - pWidth)
				pLeft = getWidth() - pWidth;
			if (pLeft > 0)
				pLeft = 0;
			if (pTop < getHeight() - pHeight)
				pTop = getHeight() - pHeight;
			if (pTop > 0)
				pTop = 0;
			imageDispRect.set(pLeft, pTop, pLeft + pWidth, pTop + pHeight);
		}
		if (pWidth > getWidth() && pHeight <= getHeight()) {
			pLeft = imageDispRect.left + dx;
			if (pLeft < getWidth() - pWidth)
				pLeft = getWidth() - pWidth;
			if (pLeft > 0)
				pLeft = 0;
			pTop = (getHeight() - pHeight) / 2;
			imageDispRect.set(pLeft, pTop, pLeft + pWidth, pTop + pHeight);
		}
		if (pWidth <= getWidth() && pHeight > getHeight()) {
			pTop = imageDispRect.top + dy;
			if (pTop < getHeight() - pHeight)
				pTop = getHeight() - pHeight;
			if (pTop > 0)
				pTop = 0;
			pLeft = (getWidth() - pWidth) / 2;
			imageDispRect.set(pLeft, pTop, pLeft + pWidth, pTop + pHeight);
		}

		// imageDispRect.set(imageDispRect.left + dx, imageDispRect.top + dy,
		// imageDispRect.right + dx, imageDispRect.bottom + dy);
	}

	public boolean isMinshow() {
		return isMiniShow;
	}

	private class GestureListener extends
			GestureDetector.SimpleOnGestureListener {

		@Override
		public boolean onDown(MotionEvent e) {
			return true;
		}

		// event when double tap occurs
		@Override
		public boolean onDoubleTap(MotionEvent e) {
			// float x = e.getX();
			// float y = e.getY();
			if (isMiniShow) {
				// ZoomPic(x, y, 3);
			} else {
				showMinSize();
			}
			return true;
		}
	}
}
